iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0

參考出處 JS 30 DAY 6

參考出處 Alex 宅幹嘛

今天要做的是 Type ahead, 當你打下關鍵字的時候,會幫你找到,有這些關鍵字的城市。

這是我很期待練習的主題,因為我不太熟,多練習多練習。

實作

練習目標

今天的重點主要放在觀念的釐清。

  1. API 讀取
  2. 陣列處理
  3. 正規表達式

實作

API 讀取

Wes Bos 在 github 內附上了 cities.json 的檔案,這個就是他用 AJAX 去 load 回來的資料。

使用純 JS 去呼叫 API
可以使用 HttpRequest 和 fetch

如果我們使用 HttpRequest,是 callback 的方式,對我來說,這個是比較容易理解的方式。寫法可以上 w3school 去複習一下。

function requestHandler(){
  console.log(JSON.parse(this.response))
}

let req = new XMLHttpRequest();

req.addEventListener('load',requestHandler)
req.open('get',endpoint)
req.send()

Wes Bos 在這個練習上用了 fetch,可以看到用 fetch 需要搭配使用 Promise,我們來理解一下下面這段 code 的意思

因為 const 是 ES6 後有的東西,所以 Wes Bos 在這裡使用了 const 他應該是想要防範 cities 被複寫。

const cities = [];
fetch(endpoint)
  .then(blob => blob.json())
  .then(data => cities.push(...data));
  

那除了上面這個寫法,可以改成更直觀一點的 let 寫法,如果是我的話,我為選擇下面的寫法。

let cities = null;
fetch(endpoint)
  .then(blob => blob.json())
  .then(data => (cities = data));

上面就是資料的部分。

功能

因為他的 search 是用打字來找關鍵字,事件就用 keyup 來做

document.querySelector('.search').addEventListener('keyup',inputHandler)

正規表達式

正規表達式 MDN

在第一個 function 可以使用 Wes Bos 的方式,也可以用 retuen x.tolocaleString() 來做到一樣的效果。

來解釋一下,這段的意思:

(/\B(?=(\d{3})+(?!\d))/g, ',')

\B: (\d{3}) 的前面要有東西,要防止 ,123 被 match 的情況出現。
\d:阿拉伯數字 (\d{3}) 表示 3 位數,要一個逗號
{}:表示個數要出現的次數
+:至少一次
(?!\d):從最後一個數字的右側(結尾)開始

整句的解釋是:

從字串結尾開始, 在每三個數字一組並加上逗號。

Regexper 可以找到圖解

比對符合字元

接著因為要比對是否有符合的字,Wes Bos 用 findMatches 來尋找符合的部分,下面可以找到 'gi' g 就是全域搜尋, i 就是不分大小寫。

這裡用 map 的原因是因為,每個 city 會產生一個 html, 所以要用 map 把這幾組的 HTML 做成陣列。

Wes Bos 使用的 join 方法使用空格把資料合起來。

找到了關鍵字後,使用 replace 的方式套用 h1 的 class 換字的背景顏色。

function numberWithCommas(x) {
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

function inputHandler(){
    const matchArray = findMatches(this.value, cities);
    const html = matchArray
    .map(place => {
    const regex = new RegExp(this.value, 'gi');
    const cityName = place.city.replace(regex, `<span class="hl">${this.value}</span>`);
    const stateName = place.state.replace(regex, `<span class="hl">${this.value}</span>`);
    return `
      <li>
        <span class="name">${cityName}, ${stateName}</span>
        <span class="population">${numberWithCommas(place.population)}</span>
      </li>
    `;
  }).join('');
  suggestions.innerHTML = html;

}

function findMatches(wordToMatch, cities) {
  return cities.filter(place => {
    const regex = new RegExp(wordToMatch, 'gi');
    return place.city.match(regex) || place.state.match(regex)
  });
}

以上,明天見


上一篇
DAY 19 Update CSS variable with JS
下一篇
DAY 21 localStorage ToDoList
系列文
半路出家,文組新手學 Javascript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言